import pandas as pd
import numpy as np
import time
from datetime import date, datetime, timedelta
import re
import os
from sqlalchemy import create_engine
from dotenv import load_dotenv
import plotly.express as px
from plotly.offline import plot
import plotly.graph_objects as go
import yfinance as yf
from pandas_datareader import data as web
#from helpers import get_yf_symbol, get_market, performance_chart
from plotly.subplots import make_subplots
import seaborn as sns
import matplotlib.pyplot as plt
import calendar
pd.options.mode.chained_assignment = None # default='warn'
seasonality = pd.read_csv("trading data export with results.csv", parse_dates=['Trading day'], dayfirst=True)
seasonality['weekday'] = seasonality['Trading day'].apply(lambda x :calendar.day_name[x.weekday()])
seasonality['Trading_time'] = pd.to_timedelta(seasonality['Trading time'])
seasonality['Trading_time'] = seasonality['Trading_time'].apply(lambda x : int(x.seconds /3600))
s_buys = seasonality[seasonality['Type'] == 'Buy']
s_sells = seasonality[seasonality['Type'] == 'Sell']
s_buys['Trading_time'] = pd.to_timedelta(s_buys['Trading time'])
s_buys['Trading_time'] = s_buys['Trading_time'].apply(lambda x : int(x.seconds /3600))
s_buys = s_buys[['weekday','Trading_time']]
s_buys = s_buys.groupby(['weekday','Trading_time']).size().reset_index().rename(columns={0:'Buy Count'})
s_sells['Trading_time'] = pd.to_timedelta(s_sells['Trading time'])
s_sells['Trading_time'] = s_sells['Trading_time'].apply(lambda x : int(x.seconds /3600))
s_sells = s_sells[['weekday','Trading_time', 'Result']]
s_sells = s_sells.groupby(['weekday','Trading_time']).agg(['sum','count']).reset_index()
s_sells.columns = ['weekday', 'Trading_time', 'Returns', 'Sell Count']
seasonality_df = seasonality.groupby(['weekday','Trading_time']).size().reset_index().rename(columns={0:'Count'})
seasonality_df = seasonality_df.merge(s_buys, on=['weekday','Trading_time'], how='left').merge(s_sells, on=['weekday','Trading_time'], how='left')
seasonality_df['pct_buy'] = seasonality_df['Buy Count'] / seasonality_df['Count']
seasonality_df['Trading_time'] = [f'0{x}:00' if x < 10 else f'{x}:00' for x in seasonality_df['Trading_time']]
seasonality_df['Returns'] = seasonality_df['Returns'].fillna(0)
seasonality_df.to_csv('weekday_bubble_plot.csv')
Trade volumes by day and hour of week
fig = px.scatter(seasonality_df, y="weekday", x="Trading_time",
size="Count", color="Returns", color_continuous_scale='RdBu', color_continuous_midpoint=0,
size_max=40, range_color=[-100,100]
)
fig.update_yaxes(categoryorder='array', categoryarray= ['Friday', 'Thursday', 'Wednesday', 'Tuesday', 'Monday'])
#fig.update_yaxes(categoryorder='array', categoryarray= ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'])
fig.update_xaxes(categoryorder='array', categoryarray= [f'0{x}:00' if x < 10 else f'{x}:00' for x in range(7,21)])
fig.layout.yaxis.showgrid=False
fig.layout.xaxis.showgrid=False
fig.show()
Trade volumes by day and hour of week aggregated by week (interactive)
seasonality = pd.read_csv("trading data export with results.csv", parse_dates=['Trading day'], dayfirst=True)
seasonality['Week_Number'] = seasonality['Trading day'].dt.strftime('%U')
seasonality['week_start'] = seasonality['Trading day'].dt.to_period('W').apply(lambda r: r.start_time)
seasonality['Trading day'] = seasonality['Trading day'].apply(lambda x :calendar.day_name[x.weekday()])
seasonality['Trading_time'] = pd.to_timedelta(seasonality['Trading time'])
seasonality['Trading_time'] = seasonality['Trading_time'].apply(lambda x : int(x.seconds /3600))
s_buys = seasonality[seasonality['Type'] == 'Buy']
s_sells = seasonality[seasonality['Type'] == 'Sell']
s_buys['Trading_time'] = pd.to_timedelta(s_buys['Trading time'])
s_buys['Trading_time'] = s_buys['Trading_time'].apply(lambda x : int(x.seconds /3600))
s_buys = s_buys[['Trading day','Trading_time','Week_Number','week_start']]
s_buys = s_buys.groupby(['week_start', 'Trading day','Trading_time']).size().reset_index().rename(columns={0:'Buy Count'})
s_sells['Trading_time'] = pd.to_timedelta(s_sells['Trading time'])
s_sells['Trading_time'] = s_sells['Trading_time'].apply(lambda x : int(x.seconds /3600))
s_sells = s_sells[['Trading day','Trading_time','Week_Number','week_start']]
s_sells = s_sells.groupby(['week_start', 'Trading day','Trading_time']).size().reset_index().rename(columns={0:'Sell Count'})
seasonality_df = seasonality.groupby(['week_start', 'Trading day','Trading_time']).size().reset_index().rename(columns={0:'Count'})
seasonality_df = seasonality_df.merge(s_buys, on=['week_start', 'Trading day','Trading_time'], how='left').merge(s_sells, on=['week_start', 'Trading day','Trading_time'], how='left')
seasonality_df = seasonality_df.fillna(0)
seasonality_df['pct_buy'] = seasonality_df['Buy Count'] / seasonality_df['Count']
seasonality_df['Trading_time'] = [f'0{x}:00' if x < 10 else f'{x}:00' for x in seasonality_df['Trading_time']]
weeks = seasonality_df['week_start'].unique()
days = seasonality_df['Trading day'].unique()
times = seasonality_df['Trading_time'].unique()
for week in weeks:
df = seasonality_df[seasonality_df['week_start'] == week]
for time in times:
for day in days:
if not ((df['Trading day'] == day) & (df['Trading_time'] == time)).any():
seasonality_df.loc[len(seasonality_df)] = [week, day, time, 0,0,0,0]
seasonality_df = seasonality_df.sort_values('week_start', ascending=True)
seasonality_df['week_start'] = seasonality_df['week_start'].dt.strftime('%d-%m-%Y')
seasonality_df = seasonality_df.reset_index(drop=True)
i = 0
lis = []
for x in range(len(seasonality_df['week_start'])):
if x % 75 == 0:
i+= 1
lis.append(i)
else:
lis.append(i)
seasonality_df['week'] = lis
fig = px.scatter(seasonality_df, x="Trading_time", y="Trading day",
size="Count", color="pct_buy", color_continuous_scale='RdBu', color_continuous_midpoint=0.5,
hover_name="Count", animation_frame='week',
size_max=50
)
fig.update_yaxes(categoryorder='array', categoryarray= ['Friday', 'Thursday', 'Wednesday', 'Tuesday', 'Monday'])
fig.update_xaxes(categoryorder='array', categoryarray= [f'0{x}:00' if x < 10 else f'{x}:00' for x in range(7,21)])
#fig.update_layout(transition = {'duration': 50000}, margin=dict(l=0,r=0,b=0,t=0))
fig.layout.updatemenus[0].buttons[0].args[1]["frame"]["duration"] = 1000
fig.show()
Trade volumes over the year
trades = pd.read_csv("trading data export with results.csv", parse_dates=['Trading day'], dayfirst=True)
days = trades.groupby(['Trading day']).size().reset_index().rename(columns={0:'Count'})
buys = trades[trades['Type'] == 'Buy'].groupby(['Trading day']).size().reset_index().rename(columns={0:'Buy Execution'})
sells = trades[trades['Type'] == 'Sell'].groupby(['Trading day']).size().reset_index().rename(columns={0:'Sell Execution'})
idx = pd.bdate_range(min(days['Trading day']), max(days['Trading day']))
days.set_index('Trading day', inplace=True)
buys.set_index('Trading day', inplace=True)
sells.set_index('Trading day', inplace=True)
days = days.reindex(idx, fill_value=0).reset_index().rename(columns={'index':'Trading day', 'Count':'Trading Activity'})
buys = buys.reindex(idx, fill_value=0).reset_index().rename(columns={'index':'Trading day'})
sells = sells.reindex(idx, fill_value=0).reset_index().rename(columns={'index':'Trading day'})
days = days.merge(buys, on=['Trading day'], how='left').merge(sells, on=['Trading day'], how='left')
#df = pd.read_csv("https://raw.githubusercontent.com/addenergyx/datasets/main/day_count.csv")
fig = px.bar(days, x='Trading day', y='Trading Activity')
#plot(fig)
fig = go.Figure(data=[
go.Bar(name='Buy Executions', x=days['Trading day'], y=days['Buy Execution']),
go.Bar(name='Sell Executions', x=days['Trading day'], y=days['Sell Execution'])
])
# Change the bar mode
fig.update_layout(barmode='stack', bargap=0)
fig.show()
Treemap of trades aggregated by Sector and Industry
trades = pd.read_csv("trading data export with results.csv", parse_dates=['Trading day'])
trades['Result'] = trades['Result'].fillna(0.0)
trades = trades.dropna(thresh=15)
trades = trades.dropna(axis=1, thresh=400)
a = trades.groupby(['Sector','Industry','Name']).count()
b = trades.groupby(['Sector','Industry','Name']).sum()
a = a.reset_index()
b = b.reset_index()
a['count'] = a['Result']
a = a[['Sector','Industry', 'Name', 'count']]
b = b[['Sector','Industry', 'Name','Result']]
c = pd.concat([a, b['Result']], axis=1)
#Weights sum to zero, can't be normalized
b['Result'] = b['Result'].astype(int)
b = b[b['Result']!=0]
fig = px.treemap(c, path=['Sector', 'Industry', 'Name'], values='count', color='Result',
color_continuous_scale='RdBu', color_continuous_midpoint=0, range_color=[-1000,1000],
#hover_data=['Ticker', 'MARKET VALUE', 'PCT']
)
fig.update_layout(margin=dict(l=0, r=0, t=0, b=0),
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
transition={
'duration': 500,
'easing': 'cubic-in-out',
}
)
#fig.update_layout(coloraxis_showscale=False)
fig.data[0].hovertemplate = '%{label}<br><br>%{value} Trades<br>£%{color}'
#fig.data[0].textinfo = 'label+text+percent entry+percent parent+value'
fig.show()
OHLC + Volume and successful/unsuccessful trades (interactive). Takes a while to load
def stock_split_adjustment(r):
portfolio = pd.read_csv("trading data export with results.csv", parse_dates=['Trading day'], dayfirst=True)
ticker = portfolio[portfolio['Ticker'] == r.Ticker]['YF_TICKER'].values[0]
aapl = yf.Ticker(ticker)
split_df = aapl.splits.reset_index()
split = split_df[split_df['Date'] > r['Trading day']]['Stock Splits'].sum()
if split > 0:
r.Execution_Price = r.Execution_Price/split
return r
def get_buy_sell(ticker):
portfolio = pd.read_csv("trading data export with results.csv", parse_dates=['Trading day'], dayfirst=True)
df = portfolio[portfolio['Ticker'] == ticker]
#df['Execution_Price'] = df['Price / share'] # Convert price to original currency
# df['Execution_Price'] = df['Price'] / df['Exchange rate'] # for emails instead of csv
df['Trading day'] = pd.to_datetime(df['Trading day']) # Match index date format
buys = df[df['Type']=='Buy']
sells = df[df['Type']=='Sell']
buys = buys.apply(stock_split_adjustment, axis=1)
sells = sells.apply(stock_split_adjustment, axis=1)
return buys, sells
def performance_chart(ticker='TSLA'):
#ticker = 'NG'
all_212_equities = pd.read_csv('stock_list.csv')
portfolio = pd.read_csv("trading data export with results.csv", parse_dates=['Trading day'], dayfirst=True)
buys, sells = get_buy_sell(ticker)
start = datetime(2020, 2, 7)
end = datetime.now()
yf_symbol = portfolio[portfolio['Ticker'] == ticker]['YF_TICKER'].values[0]
index = web.DataReader(yf_symbol, 'yahoo', start, end)
index = index.reset_index()
index['Midpoint'] = (index['High'] + index['Low']) / 2
buy_target = []
sell_target = []
for i, row in buys.iterrows():
mid = index[index['Date'] == row['Trading day']]['Midpoint'].values[0]
if row['Execution_Price'] < mid:
buy_target.append(1)
else:
buy_target.append(0)
for i, row in sells.iterrows():
mid = index[index['Date'] == row['Trading day']]['Midpoint'].values[0]
if row['Execution_Price'] > mid:
sell_target.append(1)
else:
sell_target.append(0)
buys['Target'] = buy_target
sells['Target'] = sell_target
## Discrete color graph
main_fig = make_subplots(specs=[[{"secondary_y": True}]])
fig = go.Figure(data=[go.Candlestick(x=index['Date'],
open=index['Open'],
high=index['High'],
low=index['Low'],
close=index['Adj Close'],
name='Stock')])
# fig = go.Candlestick(x=index['Date'],
# open=index['Open'],
# high=index['High'],
# low=index['Low'],
# close=index['Adj Close'],
# name='Stock')
# Must be a string for plotly to interpret numeric values as a discrete value
# https://plotly.com/python/discrete-color/
sells['Target'] = sells['Target'].astype(str)
buys['Target'] = buys['Target'].astype(str)
if len(sells) > 0:
fig1 = px.scatter(sells, x='Trading day', y='Execution_Price', color='Target')
for x in fig1.data:
if x['legendgroup'] == '1':
x['marker'] = {'color':'#E24C4F', 'line': {'color': 'yellow', 'width': 2}, 'size': 7, 'symbol': 'circle'}
x['name'] = 'Successful Sell Point'
fig.add_trace(x)
elif x['legendgroup'] == '0':
x['marker'] = {'color':'#E24C4F', 'line': {'color': 'black', 'width': 2}, 'size': 7, 'symbol': 'circle'}
x['name'] = 'Unsuccessful Sell Point'
fig.add_trace(x)
if len(buys) > 0:
fig2 = px.scatter(buys, x='Trading day', y='Execution_Price', color='Target')
#fig2.update_traces(marker=dict(color='blue'))
#fig2.update_traces(marker=dict(color='#30C296', size=7, line=dict(width=2, color='DarkSlateGrey')))
for x in fig2.data:
if x['legendgroup'] == '1':
x['marker'] = {'color':'#3D9970', 'line': {'color': 'yellow', 'width': 2}, 'size': 7, 'symbol': 'circle'}
x['name'] = 'Successful Buy Point'
fig.add_trace(x)
elif x['legendgroup'] == '0':
x['marker'] = {'color':'#3D9970','line': {'color': 'black', 'width': 2}, 'size': 7, 'symbol': 'circle'}
x['name'] = 'Unsuccessful Buy Point'
fig.add_trace(x)
for x in range(len(fig.data)):
main_fig.add_trace(fig.data[x], secondary_y=True)
# include a go.Bar trace for volumes
volume_fig = go.Figure(go.Bar(x=index['Date'], y=index['Volume'], name='Volume'))
volume_fig.update_traces(marker_color='rgb(158,202,225)', opacity=0.6)
main_fig.add_trace(volume_fig.data[0], secondary_y=False)
main_fig.update_layout(hovermode="x unified", title=f'{ticker} Stock Graph',
# legend=dict(
# yanchor="top",
# y=0.99,
# xanchor="left",
# x=0.01
# )
# showlegend=False
)
main_fig.layout.yaxis1.showgrid=False
#main_fig.show()
return main_fig #, percentage
performance_chart()
performance_chart('CCIV')
import plotly.express as px
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
portfolio = pd.read_csv("trading data export with results.csv", parse_dates=['Trading day'], dayfirst=True)
portfolio['count'] = portfolio.groupby('Name')['Name'].transform('count')
portfolio.sort_values(by='count', ascending=False, inplace=True)
#portfolio.sort_values(by='Trading day', ascending=False, inplace=True)
def company(x):
# try:
company = portfolio[portfolio['Ticker'] == x]['Name'].values[0]
dic = {'label': f'{company} ({x})', 'value': x}
# except:
# dic = {'label': str(x), 'value': x}
return dic
tickers = [company(x) for x in portfolio['Ticker'].drop_duplicates()]
# Build App
app = JupyterDash(__name__)
app.layout = html.Div([
html.H1("Vis 5"),
dcc.Loading(
dcc.Graph(id='graphy'),
),
html.Div(
[
dcc.Dropdown(
id='ticker-dropdown',
options=tickers,
value=tickers[0]['value'],
searchable=True,
#style={'margin-top':'50px'}
),
]),
#html.H1("Vis 2"),
])
# Define callback to update graph
@app.callback(Output('graphy','figure'),
[Input("ticker-dropdown", "value")])
def event_a(ticker):
return performance_chart(ticker)
# Run app and display result inline in the notebook
app.run_server(mode='inline', port=5051)